package com.zshan.clinic.admin.service.medical;

import com.fasterxml.jackson.core.type.TypeReference;
import com.zshan.clinic.admin.entity.dto.AddInfusionFeeDTO;
import com.zshan.clinic.admin.entity.dto.OrderExecDTO;
import com.zshan.clinic.admin.entity.medical.exec.RxExtExec;
import com.zshan.clinic.admin.entity.medical.exec.RxInfusionExec;
import com.zshan.clinic.admin.entity.medical.exec.base.RxExecBase;
import com.zshan.clinic.admin.entity.medical.exec.base.RxExtExecInfo;
import com.zshan.clinic.admin.entity.medical.exec.base.RxInfusionExecGroup;
import com.zshan.clinic.admin.entity.medical.exec.base.RxInfusionExecGroupDetail;
import com.zshan.clinic.admin.entity.medical.rx.RxInfusion;
import com.zshan.clinic.admin.entity.medical.rx.base.RxBase;
import com.zshan.clinic.admin.entity.medical.rx.base.RxExtInfo;
import com.zshan.clinic.admin.entity.medical.rx.base.RxInfusionGroup;
import com.zshan.clinic.admin.entity.medical.rx.base.RxInfusionGroupDetail;
import com.zshan.clinic.admin.entity.vo.*;
import com.zshan.clinic.admin.mapper.medical.SpecOrderExecMapper;
import com.zshan.clinic.admin.service.config.ClinicDictService;
import com.zshan.clinic.admin.service.stock.DrugProfileService;
import com.zshan.clinic.admin.task.AsyncTaskService;
import com.zshan.clinic.common.constant.CommonConstant;
import com.zshan.clinic.common.constant.ExecTypeConstant;
import com.zshan.clinic.common.enums.*;
import com.zshan.clinic.common.exception.BusinessFailException;
import com.zshan.clinic.common.util.json.JsonUtil;
import com.zshan.clinic.common.util.page.PageInfo;
import com.zshan.clinic.common.util.page.PageUtils;
import com.zshan.clinic.common.util.string.StringUtil;
import com.zshan.clinic.common.util.uuid.IdBuilder;
import com.zshan.clinic.database.dao.OrderExecMapper;
import com.zshan.clinic.database.dao.OrderExecRecordMapper;
import com.zshan.clinic.database.dao.OrderExecRxMapper;
import com.zshan.clinic.database.model.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.time.LocalDate;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * 执行
 * @author lichen
 */
@Service
@Slf4j
public class OrderExecService {

    @Autowired
    private OrderExecMapper orderExecMapper;

    @Autowired
    private OrderExecRxMapper orderExecRxMapper;

    @Autowired
    private OrderExecRecordMapper orderExecRecordMapper;

    @Autowired
    private ClinicMedicalService clinicMedicalService;

    @Autowired
    private DrugProfileService drugProfileService;

    @Autowired
    private ClinicDictService clinicDictService;

    @Autowired
    private SpecOrderExecMapper specOrderExecMapper;

    @Autowired
    @Lazy
    private ChargeOrderService chargeOrderService;

    @Autowired
    private AsyncTaskService asyncTaskService;

    /**
     * 查询收费记录
     * @param clinicId
     * @param orderId
     * @return
     */
    public List<ExecChargeItemVo> getChargeList(Long clinicId, Long orderId) {
        List<ChargeOrderItem> itemList = chargeOrderService.getOrderItemByRefId(clinicId,ChargeOrderItemTypeEnum.INFUSION_FEE.getValue(),orderId);
        if(CollectionUtils.isEmpty(itemList)){
            return Collections.EMPTY_LIST;
        }
        return itemList.stream().map(item -> {
            ExecChargeItemVo execChargeItemVo = new ExecChargeItemVo();
            BeanUtils.copyProperties(item, execChargeItemVo);
            return execChargeItemVo;
        }).collect(Collectors.toList());
    }

    /**
     * 查询患者执行记录
     * @param clinicId
     * @param patientId
     * @param visitDate
     * @param pageNo
     * @param pageSize
     * @return
     */
    public PageInfo<OrderExecPatientVo> getPatientExecList(Long clinicId, Long patientId, LocalDate visitDate, Integer pageNo, Integer pageSize) {
        Long totalCount = specOrderExecMapper.getPatientExecCount(clinicId,patientId,visitDate);
        if(StringUtil.isBlank(totalCount)){
            return PageInfo.build();
        }
        List<OrderExecPatientVo> execList = specOrderExecMapper.getPatientExecList(clinicId,patientId,visitDate,PageUtils.getOffset(pageNo,pageSize),pageSize);
        return new PageInfo<>(totalCount,execList);
    }

    /**
     * 添加注射费
     * @param addInfusionFee
     */
    @Transactional(rollbackFor = Exception.class)
    public void addInfusionFee(AddInfusionFeeDTO addInfusionFee) {
        if(StringUtil.isBlank(addInfusionFee.getAmount())){
            throw new BusinessFailException("请添加注射费");
        }
        if(addInfusionFee.getAmount() <= CommonConstant.DEFAULT_0){
            throw new BusinessFailException("注射费必须是正整数！");
        }
        OrderExec orderExec = getExecById(addInfusionFee.getOrderId());
        if(orderExec == null){
            throw new BusinessFailException("执行单不存在");
        }
        chargeOrderService.addInfusionFee(orderExec,addInfusionFee);
    }

    /**
     * 查询诊所今日待执行数
     * @param clinicId
     * @return
     */
    public Long getWaitingCount(Long clinicId) {
        OrderExecExample example = new OrderExecExample();
        OrderExecExample.Criteria criteria = example.createCriteria();
        criteria.andClinicIdEqualTo(clinicId);
        criteria.andVisitDateEqualTo(LocalDate.now());
        criteria.andIsDeleteEqualTo(YesOrNoEnum.NO.getValue());
        criteria.andExecStatusEqualTo(ExecStatusEnum.NOT_EXECUTED.getValue());
        return orderExecMapper.countByExample(example);
    }

    /**
     * 查询执行记录
     * @param orderId
     * @param pageNo
     * @param pageSize
     * @return
     */
    public List<OrderExecRecordVo> getRecordList(Long clinicId,Long orderId,Integer pageNo,Integer pageSize){
        return specOrderExecMapper.getRecordList(clinicId,orderId,PageUtils.getOffset(pageNo,pageSize),pageSize);
    }


    /**
     * 查询发药单详情
     * @param clinicId
     * @param orderId
     * @return
     */
    public OrderExecDetailVo getExecDetail(Long clinicId, Long orderId){
        OrderExecDetailVo orderExecDetailVo = specOrderExecMapper.getExecDetail(clinicId,orderId);
        if(orderExecDetailVo != null){
            handleExecRxInfo(orderExecDetailVo);
        }
        return orderExecDetailVo;
    }

    /**
     *
     * @param orderExecDetailVo
     */
    public void handleExecRxInfo(OrderExecDetailVo orderExecDetailVo) {
        RxExecBase rxExecBase = orderExecDetailVo.getRxInfo();
        String rxType = rxExecBase.getRxType();
        if(RxTypeEnum.INFUSION.getValue().equals(rxType)){
            RxInfusionExec rxInfusionExec = new RxInfusionExec();
            BeanUtils.copyProperties(rxExecBase,rxInfusionExec);
            rxInfusionExec.setGroupList(JsonUtil.json2Obj(rxExecBase.getRxJson(),new TypeReference<List<RxInfusionExecGroup>>() {}));
            orderExecDetailVo.setRxInfo(rxInfusionExec);
        }else if (RxTypeEnum.EXT.getValue().equals(rxType)){
            RxExtExec rxExtExec = new RxExtExec();
            BeanUtils.copyProperties(rxExecBase,rxExtExec);
            rxExtExec.setExtInfo(JsonUtil.json2Obj(rxExecBase.getRxJson(),new TypeReference<RxExtExecInfo>() {}));
            orderExecDetailVo.setRxInfo(rxExtExec);
        }
    }


    /**
     * 查询执行单列表
     * @param clinicId
     * @param patientName
     * @param visitDate
     * @param pageNo
     * @param pageSize
     * @return
     */
    public List<OrderExecPageVo> getExecList(Long clinicId, String execCategory,String patientName, LocalDate visitDate, Integer pageNo, Integer pageSize){
        //方便调试
//        if(visitDate == null){
//            visitDate = LocalDate.now();
//        }
        if(StringUtil.isNotBlank(patientName)){
            visitDate = null;
        }
//        if(StringUtil.isBlank(execCategory)){
//            execCategory = ExecCategoryEnum.INFUSION.getValue();
//        }
        return specOrderExecMapper.getExecList(clinicId,execCategory,patientName,visitDate,PageUtils.getOffset(pageNo,pageSize),pageSize);
    }


    /**
     * 支付成功创建执行单
     * @param dbChargeOrder
     * @param allExecItemList
     */
    @Transactional(rollbackFor = Exception.class)
    public void createExec(ChargeOrder dbChargeOrder, List<ChargeOrderItem> allExecItemList) {
        //获取所有的处方ID集合
        List<Long> rxIdList = allExecItemList.stream()
                .map(ChargeOrderItem::getItemRefId)
                .filter(Objects::nonNull)
                .collect(Collectors.toList());
        ClinicMedicalDetailVo medicalDetailVo = clinicMedicalService.getMedicalPayRxList(dbChargeOrder.getClinicId(),dbChargeOrder.getVisitNo(),rxIdList);
        if(medicalDetailVo == null || CollectionUtils.isEmpty(medicalDetailVo.getRxList())){
            log.info("新增执行单，没有从病历中找到对应的已支付的处方信息，付款的订单号:{}",dbChargeOrder.getOrderId());
            return;
        }
        List<OrderExecDTO> orderExecList = handleOrderExecDTO(medicalDetailVo);
        if(CollectionUtils.isEmpty(orderExecList)){
            return;
        }
        addExecOrder(orderExecList);
    }

    /**
     * 添加执行单
     * @param orderExecList
     */
    @Transactional(rollbackFor = Exception.class)
    public void addExecOrder(List<OrderExecDTO> orderExecList) {
        //批量添加执行单
        addExecOrderBatch(orderExecList);
        //批量添加执行处方
        addExecOrderRxBatch(orderExecList);
    }

    @Transactional(rollbackFor = Exception.class)
    public void addExecOrderRxBatch(List<OrderExecDTO> orderExecList) {
        List<OrderExecRx> orderExecRxList = new ArrayList<>();
        for(OrderExecDTO orderExec : orderExecList){
            OrderExecRx orderExecRx = new OrderExecRx();
            RxExecBase rxExecBase = orderExec.getRxExecBase();
            orderExecRx.setRxId(rxExecBase.getRxId());
            orderExecRx.setOrderId(orderExec.getOrderId());
            orderExecRx.setRxName(rxExecBase.getRxName());
            orderExecRx.setRxType(rxExecBase.getRxType());
            orderExecRx.setRxJson(rxExecBase.getRxJson());
            orderExecRx.setClinicId(orderExec.getClinicId());
            orderExecRx.setIsEnabled(YesOrNoEnum.YES.getValue());
            orderExecRx.setIsDelete(YesOrNoEnum.NO.getValue());
            orderExecRx.setCreateUserId(orderExec.getCreateUserId());
            orderExecRx.setCreateBy(orderExec.getCreateBy());
            orderExecRx.setCreateTime(new Date());
            orderExecRxList.add(orderExecRx);
        }
        //批量入库
        specOrderExecMapper.addExecOrderRxBatch(orderExecRxList);
    }

    @Transactional(rollbackFor = Exception.class)
    public void addExecOrderBatch(List<OrderExecDTO> orderExecList) {
        for(OrderExecDTO orderExec : orderExecList){
            orderExec.setOrderNo(IdBuilder.getUniqueId("ZX"));
            orderExec.setExecStatus(ExecStatusEnum.NOT_EXECUTED.getValue());
            orderExec.setSortNum(CommonConstant.DEFAULT_1);
            orderExec.setIsEnabled(YesOrNoEnum.YES.getValue());
            orderExec.setIsDelete(YesOrNoEnum.NO.getValue());
            orderExec.setCreateTime(new Date());
        }
        //数据库批量保存
        specOrderExecMapper.addExecOrderBatch(orderExecList);
    }

    /**
     *
     * @param medical
     * @return
     */
    public List<OrderExecDTO> handleOrderExecDTO(ClinicMedicalDetailVo medical) {
        List<OrderExecDTO> orderExecList = new ArrayList<>();
        for (RxBase rxBase : medical.getRxList()) {
            OrderExecDTO orderExec = buildOrderExec(medical);
            RxExecBase rxExecBase = new RxExecBase();
            rxExecBase.setRxId(rxBase.getRxId());
            rxExecBase.setRxName(rxBase.getRxName());
            rxExecBase.setRxType(rxBase.getRxType());
            String rxType = rxBase.getRxType();
            if(RxTypeEnum.INFUSION.getValue().equals(rxType)) {
                orderExec.setExecCategory(ExecCategoryEnum.INFUSION.getValue());
                orderExec.setExecType(ExecTypeConstant.infusion);
                rxExecBase.setRxJson(handleInfusionRxJson(rxBase.getRxJson()));
            } else if (RxTypeEnum.EXT.getValue().equals(rxType)) {
                orderExec.setExecCategory(ExecCategoryEnum.EXT.getValue());
                rxExecBase.setRxJson(handleExtRxJson(orderExec,rxBase.getRxJson()));
            }
            orderExec.setRxExecBase(rxExecBase);
            orderExecList.add(orderExec);
        }
        return orderExecList;
    }

    public String handleInfusionRxJson(String rxJsonStr) {
        List<RxInfusionGroup> groupList = JsonUtil.json2Obj(rxJsonStr, new TypeReference<List<RxInfusionGroup>>() {});
        if (CollectionUtils.isEmpty(groupList)) {
            return null;
        }
        List<RxInfusionExecGroup> execGroupList = new ArrayList<>();
        for (RxInfusionGroup rxGroup : groupList) {
            RxInfusionExecGroup execGroup = new RxInfusionExecGroup();
            BeanUtils.copyProperties(rxGroup, execGroup);
            execGroup.setNextTimes(CommonConstant.DEFAULT_1);
            execGroup.setExecStatus(ExecStatusEnum.NOT_EXECUTED.getValue());
            DictFrequencyVo dictFrequencyVo = clinicDictService.getCacheFrequency(execGroup.getFrequencyCode());
            if(dictFrequencyVo != null){
                execGroup.setTotalTimes(dictFrequencyVo.getFrequencyTimes() * execGroup.getCycle());
            }
            List<RxInfusionGroupDetail> detailList = rxGroup.getDetailList();
            if (CollectionUtils.isEmpty(detailList)) {
                continue;
            }
            List<RxInfusionExecGroupDetail> resultDetailList = new ArrayList<>();
            for (RxInfusionGroupDetail detail : detailList) {
                RxInfusionExecGroupDetail execGroupDetail = new RxInfusionExecGroupDetail();
                BeanUtils.copyProperties(detail, execGroupDetail);
                resultDetailList.add(execGroupDetail);
            }
            execGroup.setDetailList(resultDetailList);
            execGroupList.add(execGroup);
        }
        return JsonUtil.obj2Json(execGroupList);
    }

    /**
     * 外治处方
     * @param orderExec
     * @param rxJsonStr
     * @return
     */
    public String handleExtRxJson(OrderExecDTO orderExec,String rxJsonStr) {
        RxExtInfo rxExtInfo = JsonUtil.json2Obj(rxJsonStr, new TypeReference<RxExtInfo>() {});
        if (rxExtInfo == null) {
            return null;
        }
        orderExec.setExecType(rxExtInfo.getProjectType());
        RxExtExecInfo extExecInfo = new RxExtExecInfo();
        BeanUtils.copyProperties(rxExtInfo, extExecInfo);
        extExecInfo.setNextTimes(CommonConstant.DEFAULT_1);
        extExecInfo.setExecStatus(ExecStatusEnum.NOT_EXECUTED.getValue());
        DictFrequencyVo dictFrequencyVo = clinicDictService.getCacheFrequency(rxExtInfo.getFrequencyCode());
        if(dictFrequencyVo != null){
            extExecInfo.setTotalTimes(dictFrequencyVo.getFrequencyTimes() * rxExtInfo.getCycle());
        }
        return JsonUtil.obj2Json(extExecInfo);
    }

    public OrderExecDTO buildOrderExec(ClinicMedicalDetailVo medical) {
        OrderExecDTO orderExec = new OrderExecDTO();
        orderExec.setVisitNo(medical.getVisitNo());
        orderExec.setVisitDate(medical.getVisitDate());
        orderExec.setDoctorId(medical.getDoctorId());
        orderExec.setDoctorName(medical.getDoctorName());
        orderExec.setDeptId(medical.getDeptId());
        orderExec.setDeptName(medical.getDeptName());
        orderExec.setDiagnosis(medical.getDiagnosis());
        orderExec.setDiagnosisTime(medical.getDiagnosisTime());
        orderExec.setPatientId(medical.getPatientId());
        orderExec.setPatientName(medical.getPatientName());
        orderExec.setPatientGender(medical.getPatientGender());
        orderExec.setPatientPhone(medical.getPatientPhone());
        orderExec.setIdCard(medical.getIdCard());
        orderExec.setAgeYear(medical.getAgeYear());
        orderExec.setAgeMonth(medical.getAgeMonth());
        orderExec.setSolarBirthday(medical.getSolarBirthday());
        orderExec.setLunarBirthday(medical.getLunarBirthday());
        orderExec.setWeight(medical.getWeight());
        orderExec.setSystolicBp(medical.getSystolicBp());
        orderExec.setDiastolicBp(medical.getDiastolicBp());
        orderExec.setClinicId(medical.getClinicId());
        orderExec.setCreateUserId(medical.getUpdateUserId());
        orderExec.setCreateBy(medical.getUpdateBy());
        return orderExec;
    }


    public List<Long> getDrugIdList(List<RxBase> rxList) {
        List<Long> drugIdList = rxList.stream()
                .flatMap(rxBase -> {
                    String rxType = rxBase.getRxType();
                    if (RxTypeEnum.INFUSION.getValue().equals(rxType)) {
                        RxInfusion rxInfusion = (RxInfusion) rxBase;
                        return Optional.ofNullable(rxInfusion.getGroupList()).orElse(Collections.emptyList()).stream()
                                .flatMap(group -> Optional.ofNullable(group.getDetailList()).orElse(Collections.emptyList()).stream())
                                .map(RxInfusionGroupDetail::getDrugId);
                    }
                    return Stream.empty();
                })
                .collect(Collectors.toList());
        return drugIdList;
    }

    /**
     * 分页查询执行记录列表
     * @param clinicId 诊所ID
     * @param pageNo 页码
     * @param pageSize 每页条数
     * @return 分页结果
     */
    public PageInfo<OrderExecRecord> getExecRecordListByCondition(Long clinicId, Integer pageNo, Integer pageSize) {
        OrderExecRecordExample example = new OrderExecRecordExample();
        OrderExecRecordExample.Criteria criteria = example.createCriteria();
        if (clinicId != null) {
            criteria.andClinicIdEqualTo(clinicId);
        }
        criteria.andIsDeleteEqualTo(YesOrNoEnum.NO.getValue());

        Long totalCount = orderExecRecordMapper.countByExample(example);
        if (totalCount == null || totalCount == 0L) {
            return PageInfo.build();
        }

        example.setOffset(PageUtils.getOffset(pageNo, pageSize));
        example.setLimit(pageSize);
        example.setOrderByClause("create_time desc");

        List<OrderExecRecord> list = orderExecRecordMapper.selectByExample(example);
        return new PageInfo<>(totalCount, list);
    }

    /**
     * 添加执行记录
     * @param execRecord 实体
     */
    @Transactional(rollbackFor = Exception.class)
    public void addExecRecord(OrderExecRecord execRecord) {
        RxExecBase rxExecBase = validateExecRecord(execRecord);
        //保存执行记录
        Long execUserId = execRecord.getCreateUserId();
        String execBy = execRecord.getCreateBy();
        Date execTime = new Date();
        execRecord.setExecUserId(execUserId);
        execRecord.setExecBy(execBy);
        execRecord.setExecTime(execTime);
        execRecord.setIsDelete(YesOrNoEnum.NO.getValue());
        execRecord.setIsEnabled(YesOrNoEnum.YES.getValue());
        execRecord.setCreateTime(execTime);
        orderExecRecordMapper.insertSelective(execRecord);
        //更新执行单的执行次数
        updateOrderExecRx(rxExecBase,execUserId,execBy,execTime);
        //更新执行单的状态
        updateOrderExecStatus(rxExecBase,execRecord.getOrderId(),execUserId,execBy,execTime);
        //统计诊所今日营收
        StatClinicIncomeDaily statClinicIncomeDaily = new StatClinicIncomeDaily();
        statClinicIncomeDaily.setClinicId(execRecord.getClinicId());
        statClinicIncomeDaily.setExecCount(CommonConstant.DEFAULT_1);
        asyncTaskService.asyncSaveOrUpdateClinicIncome(statClinicIncomeDaily);
    }

    @Transactional(rollbackFor = Exception.class)
    public void updateOrderExecStatus(RxExecBase rxExecBase,Long orderId,Long execUserId, String execBy,Date execTime) {
        String execStatus = getExecStatus(rxExecBase);
        if(!ExecStatusEnum.EXECUTED.getValue().equals(execStatus)){
            return;
        }
        OrderExec orderExec = new OrderExec();
        orderExec.setOrderId(orderId);
        orderExec.setExecStatus(execStatus);
        orderExec.setUpdateUserId(execUserId);
        orderExec.setUpdateBy(execBy);
        orderExec.setUpdateTime(execTime);
        orderExecMapper.updateByPrimaryKeySelective(orderExec);
    }

    public String getExecStatus(RxExecBase rxExecBase) {
        String rxType = rxExecBase.getRxType();
        if(RxTypeEnum.INFUSION.getValue().equals(rxType)){
            RxInfusionExec rxInfusionExec = (RxInfusionExec) rxExecBase;
            List<RxInfusionExecGroup> rxInfusionExecGroupList = rxInfusionExec.getGroupList();
            for(RxInfusionExecGroup rxInfusionExecGroup : rxInfusionExecGroupList){
                if(!ExecStatusEnum.EXECUTED.getValue().equals(rxInfusionExecGroup.getExecStatus())){
                    return ExecStatusEnum.NOT_EXECUTED.getValue();
                }
            }
        }else {
            RxExtExec rxExtExec = (RxExtExec) rxExecBase;
            RxExtExecInfo extInfo = rxExtExec.getExtInfo();
            if(!ExecStatusEnum.EXECUTED.getValue().equals(extInfo.getExecStatus())){
                return ExecStatusEnum.NOT_EXECUTED.getValue();
            }
        }
        return ExecStatusEnum.EXECUTED.getValue();
    }

    /**
     * 修改处方的执行次数
     * @param rxExecBase
     * @param createUserId
     * @param createBy
     */
    @Transactional(rollbackFor = Exception.class)
    public void updateOrderExecRx(RxExecBase rxExecBase, Long createUserId, String createBy,Date execTime) {
        OrderExecRx orderExecRx = new OrderExecRx();
        orderExecRx.setRxId(rxExecBase.getRxId());
        String rxType = rxExecBase.getRxType();
        if(RxTypeEnum.INFUSION.getValue().equals(rxType)){
            RxInfusionExec rxInfusionExec = (RxInfusionExec) rxExecBase;
            orderExecRx.setRxJson(JsonUtil.obj2Json(rxInfusionExec.getGroupList()));
        }else {
            RxExtExec rxExtExec = (RxExtExec) rxExecBase;
            orderExecRx.setRxJson(JsonUtil.obj2Json(rxExtExec.getExtInfo()));
        }
        orderExecRx.setUpdateUserId(createUserId);
        orderExecRx.setUpdateBy(createBy);
        orderExecRx.setUpdateTime(execTime);
        orderExecRxMapper.updateByPrimaryKeySelective(orderExecRx);
    }




    /**
     * 校验执行记录参数
     * @param record 实体
     */
    public RxExecBase validateExecRecord(OrderExecRecord record) {
        if(StringUtil.isBlank(record.getExecResult())){
            throw new BusinessFailException("请填写执行结果！");
        }
        //补充必填字段、业务约束校验
        OrderExecDetailVo orderExec = getExecDetail(record.getClinicId(),record.getOrderId());
        if(orderExec == null){
            throw new BusinessFailException("执行单不存在");
        }
        if(ExecStatusEnum.EXECUTED.getValue().equals(orderExec.getExecStatus())){
            throw new BusinessFailException("该执行单已完成！");
        }
        RxExecBase rxExecBase = orderExec.getRxInfo();
        String rxType = rxExecBase.getRxType();
        if(RxTypeEnum.INFUSION.getValue().equals(rxType)){
            String groupName = record.getGroupName();
            if(StringUtil.isBlank(groupName)){
                throw new BusinessFailException("组名不能为空");
            }
            RxInfusionExec rxInfusionExec = (RxInfusionExec) rxExecBase;
            if(rxInfusionExec == null){
                throw new BusinessFailException("处方数据异常！");
            }
            RxInfusionExecGroup rxInfusionExecGroup = getRxInfusionExecGroup(groupName,rxInfusionExec.getGroupList());
            if(rxInfusionExecGroup == null){
                throw new BusinessFailException("没有找到对应的处方组！");
            }
            if(ExecStatusEnum.EXECUTED.getValue().equals(rxInfusionExecGroup.getExecStatus())){
                throw new BusinessFailException("该组已执行完成！");
            }
            //当前执行次数
            Integer nextTimes = rxInfusionExecGroup.getNextTimes();
            record.setExecTimes(nextTimes);
            //总的执行次数
            Integer totalTimes = rxInfusionExecGroup.getTotalTimes();
            if(nextTimes.equals(totalTimes)){
                //当前就是最后一次，需要把状态置为已完成
                rxInfusionExecGroup.setExecStatus(ExecStatusEnum.EXECUTED.getValue());
            }else {
                rxInfusionExecGroup.setNextTimes(nextTimes + CommonConstant.DEFAULT_1);
            }
        }else if (RxTypeEnum.EXT.getValue().equals(rxType)){
            RxExtExec rxExtExec = (RxExtExec) rxExecBase;
            if(rxExtExec == null){
                throw new BusinessFailException("处方数据异常！");
            }
            RxExtExecInfo extInfo = rxExtExec.getExtInfo();
            if(extInfo == null){
                throw new BusinessFailException("处方数据异常！");
            }
            //设置记录为当前次数
            Integer currentTimes = extInfo.getNextTimes();
            record.setExecTimes(currentTimes);
            Integer totalTimes = extInfo.getTotalTimes();
            if(currentTimes.equals(totalTimes)){
                extInfo.setExecStatus(ExecStatusEnum.EXECUTED.getValue());
            }else {
                extInfo.setNextTimes(currentTimes + CommonConstant.DEFAULT_1);
            }
        }
        record.setExecType(orderExec.getExecType());
        return rxExecBase;
    }

    /**
     * 查询执行单的输液处方组
     * @param groupName
     * @param rxInfusionExecGroupList
     * @return
     */
    public RxInfusionExecGroup getRxInfusionExecGroup(String groupName, List<RxInfusionExecGroup> rxInfusionExecGroupList) {
        return CollectionUtils.isEmpty(rxInfusionExecGroupList) ? null :
                rxInfusionExecGroupList.stream()
                        .filter(group -> groupName.equals(group.getGroupName()))
                        .findFirst()
                        .orElse(null);
    }

    /**
     * 根据ID获取执行记录详情
     * @param recordId 主键
     * @return 实体
     */
    public OrderExecRecord getExecRecordById(Long recordId) {
        if (recordId == null || recordId == 0L) {
            return null;
        }
        OrderExecRecord record = orderExecRecordMapper.selectByPrimaryKey(recordId);
        if (record == null || YesOrNoEnum.YES.getValue().equals(record.getIsDelete())) {
            return null;
        }
        return record;
    }

    /**
     * 修改执行记录
     * @param record 实体
     */
    @Transactional(rollbackFor = Exception.class)
    public void updateExecRecord(OrderExecRecord record) {
        OrderExecRecord dbRecord = getExecRecordById(record.getRecordId());
        if (dbRecord == null) {
            throw new BusinessFailException("执行记录不存在");
        }
        if(StringUtil.isBlank(record.getExecResult())){
            throw new BusinessFailException("请填写执行结果");
        }
        dbRecord.setExecResult(record.getExecResult());
        dbRecord.setUpdateUserId(record.getUpdateUserId());
        dbRecord.setUpdateBy(record.getUpdateBy());
        dbRecord.setUpdateTime(new Date());
        orderExecRecordMapper.updateByPrimaryKeySelective(dbRecord);
    }

    /**
     * 删除执行记录（逻辑删除）
     * @param record 实体
     */
    @Transactional(rollbackFor = Exception.class)
    public void deleteExecRecord(OrderExecRecord record) {
        OrderExecRecord db = getExecRecordById(record.getRecordId());
        if (db == null) {
            throw new BusinessFailException("执行记录不存在");
        }
        db.setIsDelete(YesOrNoEnum.YES.getValue());
        db.setUpdateUserId(record.getUpdateUserId());
        db.setUpdateBy(record.getUpdateBy());
        db.setUpdateTime(new Date());
        orderExecRecordMapper.updateByPrimaryKeySelective(db);
    }

    /**
     * 启用执行记录
     * @param record 实体
     */
    @Transactional(rollbackFor = Exception.class)
    public void enableExecRecord(OrderExecRecord record) {
        OrderExecRecord db = getExecRecordById(record.getRecordId());
        if (db == null) {
            throw new BusinessFailException("执行记录不存在");
        }
        if (YesOrNoEnum.YES.getValue().equals(db.getIsEnabled())) {
            return;
        }
        db.setIsEnabled(YesOrNoEnum.YES.getValue());
        db.setUpdateUserId(record.getUpdateUserId());
        db.setUpdateBy(record.getUpdateBy());
        db.setUpdateTime(new Date());
        orderExecRecordMapper.updateByPrimaryKeySelective(db);
    }

    /**
     * 停用执行记录
     * @param record 实体
     */
    @Transactional(rollbackFor = Exception.class)
    public void disableExecRecord(OrderExecRecord record) {
        OrderExecRecord db = getExecRecordById(record.getRecordId());
        if (db == null) {
            throw new BusinessFailException("执行记录不存在");
        }
        if (YesOrNoEnum.NO.getValue().equals(db.getIsEnabled())) {
            return;
        }
        db.setIsEnabled(YesOrNoEnum.NO.getValue());
        db.setUpdateUserId(record.getUpdateUserId());
        db.setUpdateBy(record.getUpdateBy());
        db.setUpdateTime(new Date());
        orderExecRecordMapper.updateByPrimaryKeySelective(db);
    }

    /**
     * 分页查询执行单处方列表
     * @param clinicId 诊所ID
     * @param pageNo 页码
     * @param pageSize 每页条数
     * @return 分页结果
     */
    public PageInfo<OrderExecRx> getExecRxListByCondition(Long clinicId, Integer pageNo, Integer pageSize) {
        OrderExecRxExample example = new OrderExecRxExample();
        OrderExecRxExample.Criteria criteria = example.createCriteria();
        if (clinicId != null) {
            criteria.andClinicIdEqualTo(clinicId);
        }
        criteria.andIsDeleteEqualTo(YesOrNoEnum.NO.getValue());

        Long totalCount = orderExecRxMapper.countByExample(example);
        if (totalCount == null || totalCount == 0) {
            return PageInfo.build();
        }

        example.setOffset(PageUtils.getOffset(pageNo, pageSize));
        example.setLimit(pageSize);
        example.setOrderByClause("create_time desc");

        List<OrderExecRx> list = orderExecRxMapper.selectByExample(example);
        return new PageInfo<>(totalCount, list);
    }

    /**
     * 添加执行单处方
     * @param execRx 实体
     */
    @Transactional(rollbackFor = Exception.class)
    public void addExecRx(OrderExecRx execRx) {
        validateExecRx(execRx);
        execRx.setIsDelete(YesOrNoEnum.NO.getValue());
        execRx.setIsEnabled(YesOrNoEnum.YES.getValue());
        execRx.setCreateTime(new Date());
        orderExecRxMapper.insertSelective(execRx);
    }

    /**
     * 校验执行单处方参数
     * @param execRx 实体
     */
    public void validateExecRx(OrderExecRx execRx) {
        // TODO 补充必填字段、业务约束校验
    }

    /**
     * 根据ID获取执行单处方详情
     * @param rxId 主键
     * @return 实体
     */
    public OrderExecRx getExecRxById(Long rxId) {
        if (rxId == null || rxId == 0L) {
            return null;
        }
        OrderExecRx execRx = orderExecRxMapper.selectByPrimaryKey(rxId);
        if (execRx == null || YesOrNoEnum.YES.getValue().equals(execRx.getIsDelete())) {
            return null;
        }
        return execRx;
    }

    /**
     * 修改执行单处方
     * @param execRx 实体
     */
    @Transactional(rollbackFor = Exception.class)
    public void updateExecRx(OrderExecRx execRx) {
        validateExecRx(execRx);
        OrderExecRx dbExecRx = getExecRxById(execRx.getRxId());
        if (dbExecRx == null) {
            throw new BusinessFailException("执行单处方不存在");
        }
        execRx.setUpdateTime(new Date());
        orderExecRxMapper.updateByPrimaryKeySelective(execRx);
    }

    /**
     * 删除执行单处方（逻辑删除）
     * @param execRx 实体
     */
    @Transactional(rollbackFor = Exception.class)
    public void deleteExecRx(OrderExecRx execRx) {
        OrderExecRx dbExecRx = getExecRxById(execRx.getRxId());
        if (dbExecRx == null) {
            throw new BusinessFailException("执行单处方不存在");
        }
        dbExecRx.setIsDelete(YesOrNoEnum.YES.getValue());
        dbExecRx.setUpdateUserId(execRx.getUpdateUserId());
        dbExecRx.setUpdateBy(execRx.getUpdateBy());
        dbExecRx.setUpdateTime(new Date());
        orderExecRxMapper.updateByPrimaryKeySelective(dbExecRx);
    }

    /**
     * 启用执行单处方
     * @param execRx 实体
     */
    @Transactional(rollbackFor = Exception.class)
    public void enableExecRx(OrderExecRx execRx) {
        OrderExecRx dbExecRx = getExecRxById(execRx.getRxId());
        if (dbExecRx == null) {
            throw new BusinessFailException("执行单处方不存在");
        }
        if (YesOrNoEnum.YES.getValue().equals(dbExecRx.getIsEnabled())) {
            return;
        }
        dbExecRx.setIsEnabled(YesOrNoEnum.YES.getValue());
        dbExecRx.setUpdateUserId(execRx.getUpdateUserId());
        dbExecRx.setUpdateBy(execRx.getUpdateBy());
        dbExecRx.setUpdateTime(new Date());
        orderExecRxMapper.updateByPrimaryKeySelective(dbExecRx);
    }

    /**
     * 停用执行单处方
     * @param execRx 实体
     */
    @Transactional(rollbackFor = Exception.class)
    public void disableExecRx(OrderExecRx execRx) {
        OrderExecRx dbExecRx = getExecRxById(execRx.getRxId());
        if (dbExecRx == null) {
            throw new BusinessFailException("执行单处方不存在");
        }
        if (YesOrNoEnum.NO.getValue().equals(dbExecRx.getIsEnabled())) {
            return;
        }
        dbExecRx.setIsEnabled(YesOrNoEnum.NO.getValue());
        dbExecRx.setUpdateUserId(execRx.getUpdateUserId());
        dbExecRx.setUpdateBy(execRx.getUpdateBy());
        dbExecRx.setUpdateTime(new Date());
        orderExecRxMapper.updateByPrimaryKeySelective(dbExecRx);
    }

    /**
     * 分页查询执行单列表
     * @param clinicId 诊所ID
     * @param pageNo 页码
     * @param pageSize 每页条数
     * @return 分页结果
     */
    public PageInfo<OrderExec> getExecListByCondition(Long clinicId, Integer pageNo, Integer pageSize) {
        OrderExecExample example = new OrderExecExample();
        OrderExecExample.Criteria criteria = example.createCriteria();
        if (clinicId != null) {
            criteria.andClinicIdEqualTo(clinicId);
        }
        criteria.andIsDeleteEqualTo(YesOrNoEnum.NO.getValue());

        Long totalCount = orderExecMapper.countByExample(example);
        if (totalCount == null || totalCount == 0) {
            return PageInfo.build();
        }

        example.setOffset(PageUtils.getOffset(pageNo, pageSize));
        example.setLimit(pageSize);
        example.setOrderByClause("create_time desc");

        List<OrderExec> list = orderExecMapper.selectByExample(example);
        return new PageInfo<>(totalCount, list);
    }

    /**
     * 添加执行单
     * @param orderExec 实体
     */
    @Transactional(rollbackFor = Exception.class)
    public void addExec(OrderExec orderExec) {
        validateExec(orderExec);
        orderExec.setIsDelete(YesOrNoEnum.NO.getValue());
        orderExec.setIsEnabled(YesOrNoEnum.YES.getValue());
        orderExec.setCreateTime(new Date());
        orderExecMapper.insertSelective(orderExec);
    }

    /**
     * 校验执行单参数
     * @param orderExec 实体
     */
    public void validateExec(OrderExec orderExec) {
        // TODO 校验逻辑补充
    }

    /**
     * 根据ID获取执行单详情
     * @param orderId 主键
     * @return 实体
     */
    public OrderExec getExecById(Long orderId) {
        if (orderId == null || orderId == 0L) {
            return null;
        }
        OrderExec exec = orderExecMapper.selectByPrimaryKey(orderId);
        if (exec == null || YesOrNoEnum.YES.getValue().equals(exec.getIsDelete())) {
            return null;
        }
        return exec;
    }

    /**
     * 修改执行单
     * @param exec 实体
     */
    @Transactional(rollbackFor = Exception.class)
    public void updateExec(OrderExec exec) {
        validateExec(exec);
        OrderExec dbExec = getExecById(exec.getOrderId());
        if (dbExec == null) {
            throw new BusinessFailException("执行单不存在");
        }
        exec.setUpdateTime(new Date());
        orderExecMapper.updateByPrimaryKeySelective(exec);
    }

    /**
     * 删除执行单（逻辑删除）
     * @param exec 实体
     */
    @Transactional(rollbackFor = Exception.class)
    public void deleteExec(OrderExec exec) {
        OrderExec dbExec = getExecById(exec.getOrderId());
        if (dbExec == null) {
            throw new BusinessFailException("执行单不存在");
        }
        dbExec.setIsDelete(YesOrNoEnum.YES.getValue());
        dbExec.setUpdateUserId(exec.getUpdateUserId());
        dbExec.setUpdateBy(exec.getUpdateBy());
        dbExec.setUpdateTime(new Date());
        orderExecMapper.updateByPrimaryKeySelective(dbExec);
    }

    /**
     * 启用执行单
     * @param exec 实体
     */
    @Transactional(rollbackFor = Exception.class)
    public void enableExec(OrderExec exec) {
        OrderExec dbExec = getExecById(exec.getOrderId());
        if (dbExec == null) {
            throw new BusinessFailException("执行单不存在");
        }
        if (YesOrNoEnum.YES.getValue().equals(dbExec.getIsEnabled())) {
            return;
        }
        dbExec.setIsEnabled(YesOrNoEnum.YES.getValue());
        dbExec.setUpdateUserId(exec.getUpdateUserId());
        dbExec.setUpdateBy(exec.getUpdateBy());
        dbExec.setUpdateTime(new Date());
        orderExecMapper.updateByPrimaryKeySelective(dbExec);
    }

    /**
     * 停用执行单
     * @param exec 实体
     */
    @Transactional(rollbackFor = Exception.class)
    public void disableExec(OrderExec exec) {
        OrderExec dbExec = getExecById(exec.getOrderId());
        if (dbExec == null) {
            throw new BusinessFailException("执行单不存在");
        }
        if (YesOrNoEnum.NO.getValue().equals(dbExec.getIsEnabled())) {
            return;
        }
        dbExec.setIsEnabled(YesOrNoEnum.NO.getValue());
        dbExec.setUpdateUserId(exec.getUpdateUserId());
        dbExec.setUpdateBy(exec.getUpdateBy());
        dbExec.setUpdateTime(new Date());
        orderExecMapper.updateByPrimaryKeySelective(dbExec);
    }

}
